﻿using System;
using System.Collections.Generic;
using System.Linq;
using Lists = Algoritmia.DataStructures.Lists;
namespace Algoritmia.Utils
{ 
    
    public static class UtilsExtensions
    {
        public static T ArgMin<T>(this IEnumerable<T> sequence, Func<T,double> function)
        {
            double? minimum = null;
            T argmin = default(T);
            
            foreach(var e in sequence)
            {
                double r = function(e);
                if ( minimum == null || minimum.Value > r)
                {
                    argmin = e;
                    minimum = r;
                }
            }
            if (minimum == null)
                throw new InvalidOperationException("Sequence contains no matching element");
            return argmin;
        }

        public static T ArgMin<T>(this IEnumerable<T> sequence, Func<T, int> function)
        {
            int? minimum = null;
            T argmin = default(T);

            foreach (var e in sequence)
            {
                int r = function(e);
                if (minimum == null || minimum.Value > r)
                {
                    argmin = e;
                    minimum = r;
                }
            }
            if (minimum == null)
                throw new InvalidOperationException("Sequence contains no matching element");
            return argmin;
        }

        public static T ArgMax<T>(this IEnumerable<T> sequence, Func<T, double> function)
        {
            double? maximum = null;
            T argMax = default(T);

            foreach (var e in sequence)
            {
                double r = function(e);
                if (maximum == null || maximum.Value < r)
                {
                    argMax = e;
                    maximum = r;
                }
            }
            if (maximum == null)
                throw new InvalidOperationException("Sequence contains no matching element");
            return argMax;
        }

        public static T ArgMax<T>(this IEnumerable<T> sequence, Func<T, int> function)
        {
            int? maximum = null;
            T argMax = default(T);

            foreach (var e in sequence)
            {
                int r = function(e);
                if (maximum == null || maximum.Value < r)
                {
                    argMax = e;
                    maximum = r;
                }
            }
            if (maximum == null)
                throw new InvalidOperationException("Sequence contains no matching element");
            return argMax;
        }

        public static Lists.IList<T> ToAlgoritmiaList<T>(this IEnumerable<T> sequence)
        {
            if ( sequence.GetType().GetInterfaces().Contains(typeof(Lists.IList<T>)))
            {
                return (Lists.IList<T>) sequence;
            }
            return AlgoritmiaFactory.Lists<T>.BuildDefault(sequence);
        }
    } 
}
